home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / SAT 2.3.8 / Libraries & Documentation / Add-ons / Graphic effects / ProgressBar.p < prev   
Text File  |  1995-09-10  |  10KB  |  337 lines

  1. {Adaptive progress bar unit}
  2. {by Ingemar Ragnemalm 1995}
  3.  
  4. {This unit draws a progress bar (for giving the user visual feedback during a long}
  5. {modal operation) in the current port. It works in color if available.}
  6.  
  7. {The difference between this and other progress bars is that this one is ADAPTIVE,}
  8. {giving accurate time indications rather than the number of operations or some}
  9. {arbitrary length.}
  10.  
  11. {You initialize the bar with InitProgressBar, which gives you a pointer to it data.}
  12. {Call AdvanceProgressBar repeatedly during your lengthy operation. Note that you}
  13. {do NOT tell how far it should move each time. AdvanceProgressBar will calculate}
  14. {that for you from the current time. When your lengthy operation is finished, call}
  15. {FinishProgressBar. It will dispose of the pointer and store the final time in the}
  16. {preference folder.}
  17.  
  18. {The first time you run a progress bar, you get a "barber pole" bar, indicating that}
  19. {the expected time is unknown. After that, the time elapsed will be stored, so}
  20. {later progress bars will be accurate. The progress bar is shown if the resource}
  21. {with the expected time did not exist.}
  22.  
  23. {Notes:}
  24. {You must provide the resource fork to your OPEN preference file for storing}
  25. {the total time.}
  26. {If you use several different progress bars, you should use different resID, so that}
  27. {they can store different times.}
  28.  
  29. unit ProgressBar;
  30.  
  31. interface
  32.  
  33. {$ifc UNDEFINED THINK_PASCAL}
  34.     uses
  35.         Types, QuickDraw, Memory, Resources, ToolUtils;
  36. {$endc}
  37.  
  38.     type
  39.         ProgressBarResRec = record
  40.                 totalTime: Longint;            {Expected time}
  41.             end;
  42.         ProgressBarResPtr = ^ProgressBarResRec;
  43.         ProgressBarResHnd = ^ProgressBarResPtr;
  44.  
  45.         ProgressBarColorRec = record
  46.                 frame, fore, back: RGBColor;
  47.             end;
  48.         ProgressBarColorPtr = ^ProgressBarColorRec;
  49.  
  50.         ProgressBarRec = record
  51.                 prefFile: Integer;                {File number of the preference file}
  52.                 resID: Integer;                {What resource number should the expected time resource have?}
  53.                 bounds: Rect;                    {The rectangle in which to draw.}
  54.                 colors: ProgressBarColorPtr;    {What colors to use?}
  55.                 hasColorQD: Boolean;
  56.                 port: GrafPtr;                {In what port?}
  57.                 dev: GDHandle;                {What device? (Most likely the main device.)}
  58.                 startTicks: Longint;            {When did we start?}
  59.                 lastLimit: Integer;            {Up to what point did we draw last time?}
  60.                 res: ProgressBarResHnd;    {Resource in which the expected time i stored.}
  61.             end;
  62.         ProgressBarPtr = ^ProgressBarRec;
  63.  
  64.     function InitProgressBar (prefFile, resID: Integer; bounds: Rect; colors: ProgressBarColorPtr): ProgressBarPtr;
  65.     function ProgressBarColors (frameRed, frameGreen, frameBlue, backRed, backGreen, backBlue, foreRed, foreGreen, foreBlue: Integer): ProgressBarColorPtr;
  66.     function ProgressBarColorsRGB (frame, back, fore: RGBColor): ProgressBarColorPtr;
  67.     procedure AdvanceProgressBar (thePB: ProgressBarPtr);
  68.     procedure FinishProgressBar (thePB: ProgressBarPtr);
  69.  
  70. {InitProgressBar: Sets up a progress bar and returns a pointer to it.}
  71. {Parameter:}
  72. {prefFile:        File number of an open resource file in which to store preferences.}
  73. {resID:        Resource number for the resource in which to save. You should use a different number}
  74. {                for every progress bar your program uses}
  75. {bounds:        The rectangle in which to draw (locl coordinates in the current port).}
  76. {colors:        Colors to draw with. Use nil for default colors.}
  77.  
  78. {ProgressBarColor and ProgressBarColorsRGB: Sets up a color record.}
  79.  
  80. {AdvanceProgressBar:    Updates the progress bar. The pointer to the progress bar is the only}
  81. {                            parameter.}
  82.  
  83. {FinishProgressBar:        Dispose the progress bar. It fills the progress bar to indicate that the}
  84. {                            operation is completed, but does NOT erase it. The pointer to the}
  85. {                            progress bar is the only parameter.}
  86.  
  87. implementation
  88.  
  89.     const
  90.         kProgressResType = 'PrgB';
  91.     var
  92.         latest: ProgressBarPtr;
  93.  
  94.     function MakeColor (red, green, blue: Integer): RGBColor;
  95.         var
  96.             theColor: RGBColor;
  97.     begin
  98.         theColor.red := red;
  99.         theColor.green := green;
  100.         theColor.blue := blue;
  101.         MakeColor := theColor;
  102.     end; {MakeColor}
  103.  
  104.     function RectWidth (r: Rect): integer;
  105.     begin
  106.         RectWidth := r.right - r.left;
  107.     end;
  108.     function RectHeight (r: Rect): integer;
  109.     begin
  110.         RectHeight := r.bottom - r.top;
  111.     end;
  112.  
  113.     function ProgressBarColors (frameRed, frameGreen, frameBlue, backRed, backGreen, backBlue, foreRed, foreGreen, foreBlue: Integer): ProgressBarColorPtr;
  114.         var
  115.             theColors: ProgressBarColorPtr;
  116.     begin
  117.         theColors := ProgressBarColorPtr(NewPtr(SizeOf(ProgressBarColorRec)));
  118.         theColors^.frame.red := frameRed;
  119.         theColors^.frame.green := frameGreen;
  120.         theColors^.frame.blue := frameBlue;
  121.         theColors^.back.red := backRed;
  122.         theColors^.back.green := backGreen;
  123.         theColors^.back.blue := backBlue;
  124.         theColors^.fore.red := foreRed;
  125.         theColors^.fore.green := foreGreen;
  126.         theColors^.fore.blue := foreBlue;
  127.         ProgressBarColors := theColors;
  128.     end; {ProgressBarColors}
  129.  
  130.     function ProgressBarColorsRGB (frame, back, fore: RGBColor): ProgressBarColorPtr;
  131.         var
  132.             theColors: ProgressBarColorPtr;
  133.     begin
  134.         theColors := ProgressBarColorPtr(NewPtr(SizeOf(ProgressBarColorRec)));
  135.         theColors^.frame := frame;
  136.         theColors^.back := back;
  137.         theColors^.fore := fore;
  138.         ProgressBarColorsRGB := theColors;
  139.     end; {ProgressBarColorsRGB}
  140.  
  141.  
  142.     function InitProgressBar (prefFile, resID: Integer; bounds: Rect; colors: ProgressBarColorPtr): ProgressBarPtr;
  143.         var
  144.             thePB: ProgressBarPtr;
  145.             ser: SysEnvRec;
  146.             saveColor: RGBColor;
  147.             saveResFile: Integer;
  148.             i: Integer;
  149.     begin
  150.         thePB := ProgressBarPtr(NewPtrClear(SizeOf(ProgressBarRec)));
  151.         if thePB <> nil then
  152.             begin
  153.                 if SysEnvirons(1, ser) = noErr then
  154.                     thePB^.hasColorQD := ser.hasColorQD;
  155.  
  156.                 thePB^.colors := colors;
  157.                 if thePB^.hasColorQD then
  158.                     if colors = nil then
  159.                         thePB^.colors := ProgressBarColors(0, 0, 0, $C000, $C000, $C000, $6000, $6000, $E000);
  160.  
  161.                 if thePB^.hasColorQD then
  162.                     GetForeColor(saveColor);
  163.                 if thePB^.hasColorQD then
  164.                     RGBForeColor(thePB^.colors^.back);
  165.                 PaintRect(bounds);
  166.                 if thePB^.hasColorQD then
  167.                     RGBForeColor(thePB^.colors^.frame)
  168.                 else
  169.                     ForeColor(blackColor);
  170.                 FrameRect(bounds);
  171.                 if thePB^.hasColorQD then
  172.                     RGBForeColor(saveColor);
  173.  
  174.                 GetPort(thePB^.port);
  175.                 if thePB^.hasColorQD then
  176.                     thePB^.dev := GetGDevice;
  177.  
  178.                 thePB^.prefFile := prefFile;
  179.                 thePB^.resID := resID;
  180.                 thePB^.bounds := bounds;
  181.                 saveResFile := CurResFile;
  182.                 UseResFile(thePB^.prefFile);
  183.                 thePB^.res := ProgressBarResHnd(GetResource(kProgressResType, resID));
  184.                 UseResFile(saveResFile);
  185.                 if thePB^.res = nil then
  186.                     for i := 1 to 15 do
  187.                         AdvanceProgressBar(thePB);
  188.                 thePB^.lastLimit := 1;
  189.                 thePB^.startTicks := TickCount;
  190.             end;
  191.         latest := thePB;
  192.         InitProgressBar := thePB;
  193.     end; {InitProgressBar}
  194.  
  195.     procedure AdvanceProgressBar (thePB: ProgressBarPtr);
  196.         var
  197.             nowTicks: Longint;
  198.             r: Rect;
  199.             nowLimit, h: Integer;
  200.             saveColor: RGBColor;
  201.             i: Integer;
  202.             saveClip: RgnHandle;
  203.             savePort: GrafPtr;
  204.             saveDevice: GDHandle;
  205.     begin
  206.         if thePB = nil then
  207.             thePB := latest;
  208.         if thePB = nil then
  209.             Exit(AdvanceProgressBar);
  210.         latest := thePB;
  211.  
  212.         GetPort(savePort);
  213.         saveDevice := GetGDevice;
  214.         SetPort(thePB^.port);
  215.         if thePB^.hasColorQD then
  216.             SetGDevice(thePB^.dev);
  217.  
  218.         if thePB^.hasColorQD then
  219.             GetForeColor(saveColor);
  220.  
  221.         if thePB^.res = nil then        {Barber pole}
  222.             begin
  223.                 thePB^.lastLimit := (thePB^.lastLimit + 1) mod 30;
  224.                 h := RectHeight(thePB^.bounds) - 3;
  225.  
  226.                 r := thePB^.bounds;
  227.                 InsetRect(r, 1, 1);
  228.                 saveClip := NewRgn;
  229.                 GetClip(saveClip);
  230.                 ClipRect(r);
  231.  
  232.                 for i := 0 to RectWidth(thePB^.bounds) div 30 do
  233.                     begin
  234.                         if thePB^.hasColorQD then
  235.                             RGBForeColor(thePB^.colors^.back)
  236.                         else
  237.                             ForeColor(whiteColor);
  238.                         MoveTo(i * 30 + thePB^.lastLimit, thePB^.bounds.bottom - 2);
  239.                         Line(h, -h);
  240.                         if thePB^.hasColorQD then
  241.                             RGBForeColor(thePB^.colors^.fore)
  242.                         else
  243.                             ForeColor(blackColor);
  244.                         MoveTo(i * 30 + 15 + thePB^.lastLimit, thePB^.bounds.bottom - 2);
  245.                         Line(h, -h);
  246.                     end;
  247.                 SetClip(saveClip);
  248.                 DisposeRgn(saveClip);
  249.             end
  250.         else
  251.             begin
  252.                 nowTicks := TickCount;
  253.                 r := thePB^.bounds;
  254.  
  255.                 r.left := thePB^.bounds.left + thePB^.lastLimit;
  256.                 nowLimit := RectWidth(thePB^.bounds) * (nowTicks - thePB^.startTicks) div thePB^.res^^.totalTime;
  257.                 if nowLimit = thePB^.lastLimit then
  258.                     begin
  259.                     end;
  260.                 if nowLimit < thePB^.lastLimit then
  261.                     begin
  262.                     end;
  263.                 if nowLimit > RectWidth(thePB^.bounds) - 2 then
  264.                     nowLimit := RectWidth(thePB^.bounds) - 2;
  265.                 r.right := thePB^.bounds.left + nowLimit;
  266.                 r.top := thePB^.bounds.top + 1;
  267.                 r.bottom := thePB^.bounds.bottom - 1;
  268.                 if thePB^.hasColorQD then
  269.                     RGBForeColor(thePB^.colors^.fore);
  270.                 PaintRect(r);
  271.                 thePB^.lastLimit := nowLimit;
  272.             end;
  273.  
  274.         if thePB^.hasColorQD then
  275.             RGBForeColor(saveColor);
  276.         SetPort(savePort);
  277.         SetGDevice(saveDevice);
  278.     end; {AdvanceProgressBar}
  279.  
  280.     procedure FinishProgressBar (thePB: ProgressBarPtr);
  281.         var
  282.             finalTicks: Longint;
  283.             saveResFile: Integer;
  284.             r: Rect;
  285.             saveColor: RGBColor;
  286.             savePort: GrafPtr;
  287.             saveDevice: GDHandle;
  288.     begin
  289.         if thePB = nil then
  290.             thePB := latest;
  291.         if thePB = nil then
  292.             Exit(FinishProgressBar);
  293.  
  294.         GetPort(savePort);
  295.         saveDevice := GetGDevice;
  296.         SetPort(thePB^.port);
  297.         if thePB^.hasColorQD then
  298.             SetGDevice(thePB^.dev);
  299.  
  300.         if thePB^.hasColorQD then
  301.             GetForeColor(saveColor);
  302.         finalTicks := TickCount;
  303.         saveResFile := CurResFile;
  304.         UseResFile(thePB^.prefFile);
  305.         if thePB^.res = nil then
  306.             begin
  307.                 thePB^.res := ProgressBarResHnd(NewHandle(SizeOf(ProgressBarResRec)));
  308.                 AddResource(Handle(thePB^.res), kProgressResType, thePB^.resID, 'Progress bar data');
  309.             end
  310.         else
  311.             begin
  312.                 r.left := thePB^.bounds.left + thePB^.lastLimit;
  313.                 r.right := thePB^.bounds.right - 1;
  314.                 r.top := thePB^.bounds.top + 1;
  315.                 r.bottom := thePB^.bounds.bottom - 1;
  316.                 if thePB^.hasColorQD then
  317.                     RGBForeColor(thePB^.colors^.fore);
  318.                 PaintRect(r);
  319.             end;
  320.         thePB^.res^^.totalTime := finalTicks - thePB^.startTicks;
  321.         ChangedResource(Handle(thePB^.res));
  322.         UpdateResFile(thePB^.prefFile);
  323.         UseResFile(saveResFile);
  324.  
  325.         if thePB^.hasColorQD then
  326.             RGBForeColor(saveColor);
  327.  
  328.         if thePB^.colors <> nil then
  329.             DisposePtr(Ptr(thePB^.colors));
  330.         DisposePtr(Ptr(thePB));
  331.         latest := nil;
  332.         SetPort(savePort);
  333.         SetGDevice(saveDevice);
  334.     end; {FinishProgressBar}
  335.  
  336.  
  337. end.